﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClearingGraphAutomaton.Base
{
    partial class Graph
    {
        /// <summary>
        /// Class representing the edge of the 2D graph.
        /// </summary>
        public class Edge
        {
            /// <summary>
            /// The orientation of the edge.
            /// </summary>
            public enum EdgeOrientation
            {
                /// <summary>
                /// Unspecified orientation.
                /// </summary>
                None,

                /// <summary>
                /// Vertical up.
                /// </summary>
                Up,

                /// <summary>
                /// Diagonal up and right.
                /// </summary>
                UpRight,

                /// <summary>
                /// Horizontal right.
                /// </summary>
                Right,

                /// <summary>
                /// Diagonal down and right.
                /// </summary>
                DownRight,

                /// <summary>
                /// Vertical down.
                /// </summary>
                Down,

                /// <summary>
                /// Diagonal down and left.
                /// </summary>
                DownLeft,

                /// <summary>
                /// Horizontal left.
                /// </summary>
                Left,

                /// <summary>
                /// Diagonal up and left.
                /// </summary>
                UpLeft
            }

            /// <summary>
            /// Creates the instance of the edge.
            /// </summary>
            /// <param name="fromNode">Source node.</param>
            /// <param name="toNode">Destination node.</param>
            /// <param name="orientation">Orientation of the edge.</param>
            public Edge(Node fromNode, Node toNode, EdgeOrientation orientation)
            {
                this.FromNode = fromNode;
                this.ToNode = toNode;
                this.Orientation = orientation;
            }

            /// <summary>
            /// Source node.
            /// </summary>
            public Node FromNode { get; protected set; }

            /// <summary>
            /// Destination node.
            /// </summary>
            public Node ToNode { get; set; }

            /// <summary>
            /// Orientation of the edge.
            /// </summary>
            public EdgeOrientation Orientation { get; set; }

            /// <summary>
            /// Returns the opposite orientation of the given edge orientation.
            /// </summary>
            /// <param name="orientation">The input edge orientation.</param>
            /// <returns>The opposite orientation of the given edge orientation.</returns>
            public static EdgeOrientation OppositeOrientation(EdgeOrientation orientation)
            {
                switch (orientation)
                {
                    case EdgeOrientation.None: return EdgeOrientation.None;
                    case EdgeOrientation.Up: return EdgeOrientation.Down;
                    case EdgeOrientation.UpRight: return EdgeOrientation.DownLeft;
                    case EdgeOrientation.Right: return EdgeOrientation.Left;
                    case EdgeOrientation.DownRight: return EdgeOrientation.UpLeft;
                    case EdgeOrientation.Down: return EdgeOrientation.Up;
                    case EdgeOrientation.DownLeft: return EdgeOrientation.UpRight;
                    case EdgeOrientation.Left: return EdgeOrientation.Right;
                    case EdgeOrientation.UpLeft: return EdgeOrientation.DownRight;
                    default: throw new InvalidProgramException("Unknown edge orientation.");
                }
            }

            /// <summary>
            /// Returns the string representation of the orientation of this edge.
            /// </summary>
            /// <returns>String representation of the orientation of this edge.</returns>
            public override string ToString()
            {
                switch (this.Orientation)
                {
                    case EdgeOrientation.None: return "";
                    case EdgeOrientation.Up: return "\u2191";
                    case EdgeOrientation.UpRight: return "\u2197";
                    case EdgeOrientation.Right: return "\u2192";
                    case EdgeOrientation.DownRight: return "\u2198";
                    case EdgeOrientation.Down: return "\u2193";
                    case EdgeOrientation.DownLeft: return "\u2199";
                    case EdgeOrientation.Left: return "\u2190";
                    case EdgeOrientation.UpLeft: return "\u2196";
                    default: throw new InvalidProgramException("Unknown edge orientation.");
                }
            }
        }
    }
}
